// services/taskService.js

const {
  queryWorkflowResult,
  runRenderWorkflow
} = require('../core/cozeClient')
const {
  fetchTaskById,
  updateTaskStatus
} = require('../core/databaseService')

/** 
 * 刷新单个任务的状态并更新数据库
 * @param {string} taskId - 任务ID
 * @param {boolean} [forceUpdate=false] - 是否即使状态未变化也更新 result
 * @returns {Promise<object>} - 返回刷新后的任务对象
 */
async function refreshAndUpdateTask(taskId, forceUpdate = false) {
  const task = await fetchTaskById(taskId);
  if (!task) throw new Error(`任务不存在: ${taskId}`);

  // 没有执行ID或workflowID的话无法查询
  if (!task.executeId || !task.workflowId) {
    return task;
  }

  const cozeResponse = await queryWorkflowResult(task.executeId, task.workflowId, task.taskType);

  if (!cozeResponse) return task;

  const workflowResult = cozeResponse?.data?.[0];

  let newStatus = task.status;
  let result = task.result || {};

  if (!workflowResult) {
    // ⛔ 请求失败但我们已有本地状态
    const localStatus = result.execute_status || result.executeStatus || result.status;

    if (localStatus === 'Success' || localStatus === 'Succeeded' || localStatus === 'completed') {
      // ✅ 已成功，保持成功状态
      newStatus = 'completed';
      result = {
        ...result,
        status: '成功'
      };
    } else if (localStatus === 'failed' || localStatus === 'error') {
      // ❌ 已失败
      newStatus = 'failed';
      result = {
        ...result,
        status: '失败'
      };
    } else {
      // 🚧 否则维持查询中
      newStatus = 'running';
      result = {
        ...result,
        status: '查询中'
      };
    }
  } else {
    const status = workflowResult.execute_status || workflowResult.executeStatus;

    switch (status) {
      case 'Success':
        let finalOutput = {};
        let res = {};
        try {
          finalOutput = parseWorkflowOutput(workflowResult);
          res = parseFinalOutput(finalOutput);

          if (res.type === "draft") {
            // ⚠️ 安全机制：Coze 不应该再返回 draft 了
            console.warn(`[异常] 任务 ${taskId} 返回了 draft 类型，请检查 Coze 工作流配置`);
            console.warn(`Draft URL: ${res.url}`);

            // 将其视为完成，但标记需要人工检查
            newStatus = 'completed';
            result = {
              debugUrl: res.debugUrl,
              status: res.status,
              videoUrl: res.url,
              executeStatus: 'Success',
              needsManualCheck: true,
              warning: 'Coze返回了draft类型，请检查工作流配置'
            };
          } else if (res.type === 'video') {
            newStatus = 'completed';
            result = {
              debugUrl: res.debugUrl,
              status: res.status,
              videoUrl: res.url,
              executeStatus: 'Success',
            };
            // 积分已在提交时扣除，这里不再扣除
          } else {
            result = {
              debugUrl: res.debugUrl,
              status: res.status,
              finalOutput: finalOutput,
            }
          }

        } catch (err) {
          result = {
            debugUrl: workflowResult.debug_url,
            error: '解析结果失败',
            err_status: status,
            err: err,
            rawOutput: workflowResult.output || '出错',
            finalOutput: finalOutput || '出错',
            res: res
          };
        }
        break;

      case 'Running':
        newStatus = 'running';
        result = {
          ...result,
          debugUrl: workflowResult.debug_url || result.debugUrl || null,
          status: '任务运行中',
          executeStatus: status
        };
        break;

      default:
        // 执行失败，尝试重试
        const shouldRetry = await retryFailedTask(task);

        if (shouldRetry) {
          // 重试成功，保持 running 状态
          newStatus = 'running';
          result = {
            ...result,
            status: '任务运行中',
            debugUrl: workflowResult.debug_url
          };
        } else {
          // 达到重试上限，标记为 failed
          // 记录失败信息供后续人工审核（积分不退还）
          newStatus = 'failed';
          result = {
            error: workflowResult.error_message || '工作流执行失败',
            debugUrl: workflowResult.debug_url,
            failureReason: workflowResult.error_message || '执行失败',
            retryCount: task.retryCount,
            maxRetries: task.maxRetries,
            pointsDeducted: task.pointsDeducted,
            failedAt: new Date(),
            needsManualReview: true // 标记需要人工审核
          };
        }
    }
  }

  // 仅当状态变化或强制刷新时，才更新数据库
  if (forceUpdate || newStatus !== task.status) {
    await updateTaskStatus(taskId, newStatus, result);
  } else {
    await updateTaskStatus(taskId, newStatus, result);
  }

  // 返回刷新后最新数据
  const updatedTask = await fetchTaskById(taskId);

  return updatedTask;
}


// 解析到 工作流的最后节点输出 finalOutput
function parseWorkflowOutput(workflowResult) {
  if (!workflowResult) throw new Error("workflowResult 为空");

  // 解析 output（外层 JSON）
  const outerOutput =
    typeof workflowResult.output === "string" ?
    JSON.parse(workflowResult.output) :
    workflowResult.output;

  // 再解析 Output（内层 JSON）
  const finalOutput =
    typeof outerOutput.Output === "string" ?
    JSON.parse(outerOutput.Output) :
    outerOutput.Output;

  return finalOutput;
}

/**
 * 递归解析嵌套的 JSON 字符串
 * @param {*} value - 待解析的值
 * @returns {*} 解析后的值
 */
function recursiveParseJSON(value) {
  // 如果不是字符串，直接返回
  if (typeof value !== 'string') {
    return value;
  }

  try {
    // 尝试解析 JSON
    const parsed = JSON.parse(value);

    // 如果解析后还是字符串，继续递归解析
    if (typeof parsed === 'string') {
      return recursiveParseJSON(parsed);
    }

    // 如果解析后是对象或数组，返回
    return parsed;
  } catch (e) {
    // 解析失败，说明不是 JSON 字符串，直接返回原值
    return value;
  }
}

/**
 * 智能判断字符串是否为视频链接
 * @param {string} url - 待检测的 URL
 * @returns {boolean} 是否为视频链接
 */
function isVideoUrl(url) {
  if (!url || typeof url !== 'string') {
    return false;
  }

  // 必须是 http/https 开头
  if (!url.startsWith('http://') && !url.startsWith('https://')) {
    return false;
  }

  const lowerUrl = url.toLowerCase();

  // 1. 检查视频文件后缀
  const videoExtensions = ['.mp4', '.mov', '.avi', '.mkv', '.flv', '.webm', '.m4v', '.wmv'];
  if (videoExtensions.some(ext => lowerUrl.endsWith(ext))) {
    return true;
  }

  // 2. 检查路径特征（包含 /videos/ 或 /video/）
  if (lowerUrl.includes('/videos/') || lowerUrl.includes('/video/')) {
    return true;
  }

  // 3. 检查域名特征（CDN 或对象存储服务）
  const storageKeywords = ['cdn', 'cos', 'oss', 's3', 'storage', 'cloudfront', 'amazonaws'];
  if (storageKeywords.some(keyword => lowerUrl.includes(keyword))) {
    // 如果域名包含存储关键词，且 URL 看起来像资源链接（包含文件 ID 或 hash）
    // 通过检查是否有长字符串片段来判断
    const hasLongSegment = url.split('/').some(segment => segment.length > 20);
    if (hasLongSegment) {
      return true;
    }
  }

  return false;
}

/**
 * 解析 finalOutput.output 字段，提取输出类型和视频链接
 * @param {object} finalOutput - 工作流解析后的结果对象（即 parseWorkflowOutput 结果）
 * @returns {object} 结构化信息
 * {
 *   type: 'video' | 'draft' | 'unknown',
 *   url: string | null,
 *   debugUrl: string | null,
 *   status: string
 * }
 */
function parseFinalOutput(finalOutput) {
  if (!finalOutput || typeof finalOutput !== 'object') {
    return {
      type: 'unknown',
      url: null,
      debugUrl: null,
      status: '无效的 finalOutput'
    };
  }

  const debugUrl = finalOutput.debug_url || null;
  let url = null;
  let type = 'unknown';
  let status = finalOutput.status || '未定义状态';

  // ------- 🟢 处理 output 字段 -------
  if (finalOutput.output) {
    // 先递归解析，确保得到最终值
    let outputVal = recursiveParseJSON(finalOutput.output);

    // 如果递归解析后得到对象，且对象有 output 字段，继续提取
    if (outputVal && typeof outputVal === 'object' && !Array.isArray(outputVal) && outputVal.output) {
      outputVal = recursiveParseJSON(outputVal.output);
    }

    // ✅ 情况1：字符串（可能是视频链接）
    if (typeof outputVal === 'string') {
      if (isVideoUrl(outputVal)) {
        url = outputVal;
        type = 'video';
        status = '视频解析成功';
      } else {
        status = '字符串类型 output，但不是视频链接';
      }
    }

    // ✅ 情况2：数组（从后往前查找视频链接）
    else if (Array.isArray(outputVal)) {
      // 过滤出非空字符串
      const validUrls = outputVal.filter(u => typeof u === 'string' && u.trim());

      // 从后往前查找第一个视频链接
      for (let i = validUrls.length - 1; i >= 0; i--) {
        if (isVideoUrl(validUrls[i])) {
          url = validUrls[i];
          type = 'video';
          status = '视频解析成功';
          break;
        }
      }

      if (!url) {
        status = '数组类型 output，但未找到视频链接';
      }
    }

    // ✅ 情况3：对象（可能包含嵌套的视频链接字段）
    else if (outputVal && typeof outputVal === 'object') {
      // 尝试常见的视频 URL 字段名
      const possibleFields = ['video_url', 'videoUrl', 'url', 'file_url', 'fileUrl'];
      for (const field of possibleFields) {
        if (outputVal[field] && isVideoUrl(outputVal[field])) {
          url = outputVal[field];
          type = 'video';
          status = '视频解析成功';
          break;
        }
      }

      if (!url) {
        status = '对象类型 output，但未找到视频链接字段';
      }
    }

    // ✅ 情况4：无法识别的类型
    else {
      status = `未识别的 output 类型: ${typeof outputVal}`;
    }
  }

  // ------- 🟡 处理草稿逻辑 -------
  else if (finalOutput.draft_url) {
    url = finalOutput.draft_url;
    type = 'draft';
    status = '草稿输出（待云渲染）';
  }

  // ------- 🔴 未检测到 output -------
  else {
    type = 'unknown';
    url = null;
    status = '未检测到有效 output 或 draft_url';
  }

  return {
    type,
    url,
    debugUrl,
    status
  };
}





/**
 * 查询云渲染工作流结果并更新数据库
 * @param {string} taskId - 原任务ID
 * @returns {Promise<object>} 返回更新后的任务对象
 */
async function refreshRenderWorkflowResult(taskId) {
  const task = await fetchTaskById(taskId);
  if (!task) throw new Error(`任务不存在: ${taskId}`);

  // 如果没有 render_executeId 或 workflowId，无法查询云渲染结果
  const renderExecuteId = task.result?.render_executeId;
  const workflowId = '7563522028675317799'; // 固定的 查询渲染结果工作流 
  if (!renderExecuteId) {
    return task;
  }

  const cozeResponse = await queryWorkflowResult(renderExecuteId, workflowId, '云渲染');
  if (!cozeResponse) return task;

  const renderResult = cozeResponse?.data?.[0];
  if (!renderResult) return task;

  const renderStatus = renderResult.execute_status || renderResult.executeStatus;

  let newStatus = task.status;
  let result = {
    ...task.result,
    renderStatus: renderStatus
  };

  let finalOutput = {}

  switch (renderStatus) {
    case 'Success': {
      try {
        finalOutput = parseWorkflowOutput(renderResult);
        if (finalOutput.status === 'succeed') {
          newStatus = 'completed';
          result = {
            ...result,
            render_status: 'succeed',
            videoUrl: finalOutput.video_url
          };
          // 积分已在提交时扣除，这里不再扣除
        } else {
          result = {
            ...result,
            render_status: 'rendering',
          }
        }
      } catch (err) {
        newStatus = 'failed';
        result = {
          ...result,
          render_status: 'failed',
          error: '云渲染结果解析失败',
          rawError: err.message
        };
      }
      break;
    }

    case 'Running':
      newStatus = 'rendering';
      result = {
        ...result,
        render_status: 'rendering',
        status: '云渲染中'
      };
      break;

    default:
      newStatus = 'failed';
      result = {
        ...result,
        render_status: 'failed',
        status: '云渲染失败',
        error: renderResult.error_message || '云渲染未成功',
      };
  }

  const updateRes = {
    ...result,
    finalOutput: finalOutput
  }
  // 更新数据库状态
  await updateTaskStatus(taskId, newStatus, updateRes);

  // 返回更新后的任务
  return await fetchTaskById(taskId);
}



/**
 * 重试失败的任务
 * @param {object} task - 失败的任务对象
 * @returns {Promise<boolean>} - 返回是否触发了重试
 */
async function retryFailedTask(task) {
  const {
    submitWorkflow
  } = require('./cozeClient');
  const {
    updateTaskStatus
  } = require('./databaseService');

  // 检查是否达到最大重试次数
  if (task.retryCount >= task.maxRetries) {
    return false;
  }

  // 等待 5 秒
  await new Promise(resolve => setTimeout(resolve, 5000));

  try {
    const workflowResponse = await submitWorkflow(task.workflowId, task.parameters, task.taskType);

    if (workflowResponse?.execute_id) {
      await updateTaskStatus(task.taskId, 'running', task.result, {
        retryCount: task.retryCount + 1,
        lastRetryAt: new Date(),
        executeId: workflowResponse.execute_id,
        debugUrl: workflowResponse.debug_url
      });
      return true;
    }
  } catch (error) {
    console.error(`重试失败:`, error);
  }

  return false;
}

/**
 * 轻量级查询任务状态（仅读取数据库，不调用 Coze API）
 * 用于前端用户查询，快速返回当前状态
 * @param {string} taskId - 任务ID
 * @returns {Promise<object>} - 返回任务对象
 */
async function getTaskStatus(taskId) {
  const task = await fetchTaskById(taskId);
  if (!task) throw new Error(`任务不存在: ${taskId}`);
  return task;
}

module.exports = {
  refreshAndUpdateTask,
  retryFailedTask,
  getTaskStatus
}